<?php

declare(strict_types=1);

namespace App\Controller\v1;

use App\Controller\AbstractController;
use App\Service\SignInService;
use App\Service\UserService;
use App\Exception\BusinessException;
use Hyperf\Context\Context;
use Hyperf\DbConnection\Db;
use Hyperf\Di\Annotation\Inject;
use Hyperf\HttpServer\Annotation\Controller;
use Hyperf\HttpServer\Annotation\PostMapping;
use Hyperf\HttpServer\Annotation\GetMapping;
use Hyperf\HttpServer\Contract\RequestInterface;
use Hyperf\HttpServer\Contract\ResponseInterface;

#[Controller(prefix: "/api/v1/signin")]
class SigninController extends AbstractController
{
    #[Inject]
    protected SignInService $signInService;

    #[Inject]
    protected UserService $userService;

    /**
     * 每日签到
     * @param RequestInterface $request
     * @return array|ResponseInterface
     */
    #[PostMapping("checkin")]
    public function checkin(RequestInterface $request): array|ResponseInterface
    {
        try {
            $userId = (int)Context::get("login_user_id");

            // 执行签到
            $result = $this->signInService->signIn($userId);

            // 返回签到成功结果
            return $this->success([
                'signed' => true,
                'continuous_days' => $result['continuous_days'],
                'total_days' => $result['total_days'],
                'points_earned' => $result['points_earned']
            ], '签到成功');

        } catch (BusinessException $e) {
            // 处理业务异常（如已签到）
            return $this->fail($e->getCode(), $e->getMessage());
        } catch (\Exception $e) {
            // 处理其他异常
            return $this->fail(500, '签到失败，请稍后重试' . $e->getMessage());
        }
    }

    /**
     * 获取用户签到状态和数据
     *  param $month string 日期，格式: YYYY-MM-DD，默认今日
     * @param RequestInterface $request
     * @return array
     */
    #[GetMapping("status")]
    public function status(RequestInterface $request): array
    {
        $params = $this->parseParams($request);
        try {
            $userId = (int)Context::get("login_user_id");

            // 获取查询参数
            $month = $params['month'] ?? date('Y-m');//月份，格式: YYYY-MM，默认当前月

            // 获取连续签到天数
            $continuousDays = $this->signInService->getContinuousDays($userId);

            // 获取总签到天数
            $totalDays = $this->signInService->getTotalSignInDays($userId);

            // 获取月度签到数据
            $monthData = $this->signInService->getMonthSignInData($userId, $month);

            return $this->success([
                'continuous_days' => $continuousDays,
                'total_days' => $totalDays,
                'month_data' => $monthData,
                'current_month' => $month
            ]);

        } catch (\Exception $e) {
            return $this->fail(500, '获取签到状态失败');
        }
    }


    /**
     *
     * 获取当日签到排行榜
     * param $date 日期，格式: YYYY-MM-DD，默认今日
     * param $limit 返回数量，默认100
     * @param RequestInterface $request
     * @return array
     */
    #[GetMapping("rank")]
    public function rank(RequestInterface $request): array
    {
        $params = $this->parseParams($request);
        try {
            // 获取查询参数

            $date = $params['date'] ?? date('Y-m-d');

            $limit = $params['limit'] ?? 100;

            // 获取排行榜数据
            $rankData = $this->signInService->getTodayRank($limit);

            // 格式化排行榜数据
            $rank = [];
            foreach ($rankData as $index => $userId) {
                try {
                    $userInfo = $this->userService->getUserById((string)$userId);
                    $rank[] = [
                        'rank' => $index + 1,
                        'user' => [
                            'id' => $userInfo['id'],
                            'name' => $userInfo['name'],
                            'avatar' => $userInfo['avatar'],
                        ],
                        'signed_at' => $this->getSignInTime($userId, $date)
                    ];
                } catch (BusinessException $e) {
                }

            }

            return $this->success([
                'rank' => $rank,
                'date' => $date,
                'total' => count($rankData)
            ]);

        } catch (\Exception $e) {
            return $this->fail(500, '获取排行榜失败');
        }
    }

    /**
     * 获取用户签到时间
     * @param int $userId
     * @param string $date
     * @return string
     */
    private function getSignInTime(int $userId, string $date): string
    {
        $signLog = DB::table('user_signin_logs')
            ->where(['user_id' => $userId, 'signin_date' => $date])
            ->first();

        return $signLog->created_at ?? '';
    }
}
